#property copyright "Copyright 2012"
#property link      "mingxinhe@gmail.com"

#property indicator_chart_window
#property indicator_buffers 4
#property  indicator_color1  Red
#property  indicator_color2  Aqua
#property  indicator_color3  Red
#property  indicator_width3  2
#property  indicator_color4  DodgerBlue
#property  indicator_width4  2

extern int EMA.Short.Period=13;
extern int EMA.Short.Shift=0;
extern int EMA.Long.Period=20;
extern int EMA.Long.Shift=0;
extern string EMA.Applied.Price.Desc = "0:PRICE_CLOSE;1:PRICE_OPEN;2:PRICE_HIGH;3:PRICE_LOW";
extern int EMA.Applied.Price = 0;
extern string EMA.Method.Desc = "0:MODE_SMA;1:MODE_EMA;2:MODE_SMMA;3:MODE_LWMA";
extern int EMA.Method=1;
extern bool EMAShort.Above.EMALong = true;
extern int Max.Iterations = 20;
extern int Interval.Secs = 10;
extern color Down.Arrow.Color=Red;
extern int Down.Arrow.Thickness=2;
extern color Up.Arrow.Color=Aqua;
extern int Up.Arrow.Thickness=2;
extern color EMA.Short.Color=Red;
extern string EMA.Short.Style.Help = "Valid when EMA.Short.Thickness=1; 0:STYLE_SOLID; 1:STYLE_DASH";
extern int EMA.Short.Style=STYLE_DASH;
extern int EMA.Short.Thickness=2;
extern color EMA.Long.Color=DodgerBlue;
extern string EMA.Long.Style.Help = "Valid when EMA.Long.Thickness=1; 0:STYLE_SOLID; 1:STYLE_DASH";
extern int EMA.Long.Style=STYLE_DASH;
extern int EMA.Long.Thickness=2;
extern bool Text.Alert = true;
extern bool Sound.Alert = true;
extern bool Email.Alert = true;
extern string SoundFileName = "Alert.wav";

string    GlobalPrefixBase = "", GlobalPrefix = "";
//---- buffers
double upArrow[];
double downArrow[];
//---- buffers
double EMAFastBuffer[];
double EMASlowBuffer[];

int digitFactor = 1;
datetime lastTime, lastAlertTime,firstTime;
bool upArrowSignal = false;
bool downArrowSignal = false;
int iterationTimes;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
  //---- 6 additional buffers are used for counting.   
   if(Bid<10 && Digits==5) { digitFactor=10;}
   if(Bid<10 && Digits==4) { digitFactor= 1;}

   if(Bid>10 && Digits==3) { digitFactor=10;}
   if(Bid>10 && Digits==2) { digitFactor= 1;} 
   
//---- drawing settings 
   SetIndexStyle(0,DRAW_ARROW, EMPTY, Down.Arrow.Thickness, Down.Arrow.Color);
   SetIndexArrow(0,234);
   SetIndexBuffer(0, downArrow);
      
   SetIndexStyle(1,DRAW_ARROW, EMPTY, Up.Arrow.Thickness, Up.Arrow.Color);
   SetIndexArrow(1,233);
   SetIndexBuffer(1, upArrow);      
      
   SetIndexBuffer(2,EMAFastBuffer);
   SetIndexStyle(2, DRAW_LINE, EMA.Short.Style, EMA.Short.Thickness, EMA.Short.Color);
   
   SetIndexBuffer(3,EMASlowBuffer);  
   SetIndexStyle(3,DRAW_LINE, EMA.Long.Style, EMA.Long.Thickness, EMA.Long.Color);
   
      
   IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
   
   iterationTimes = Max.Iterations;  
   
   GlobalPrefixBase = "fgm/" + Symbol() + "#" + Symbol() + EMA.Short.Period + EMA.Long.Period + EMAShort.Above.EMALong;
   GlobalPrefix = GlobalPrefixBase + "-";
    
   if (!GlobalCheck("startTime"))
   {
       firstTime = TimeCurrent();
       GlobalSet("startTime", TimeCurrent());
   } 
   else
   {
       firstTime = GlobalGet("startTime");
   } 
   
//---- initialization done
   return(0);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+

int deinit()
{
//---- TODO: add your code here
// --------------------------
   //FGM_BA -- Check on reason for de-init and clear Globals if appropriate
  switch( UninitializeReason() ) {
  //case REASON_CHARTCLOSE:
    case REASON_REMOVE:
    case REASON_ACCOUNT:
      GlobalDel("startTime");
  }
   return(0);
}

//+------------------------------------------------------------------+
//| Moving Averages Convergence/Divergence                           |
//+------------------------------------------------------------------+
int start()
{  
   double AvgRange;

   if(Bars<=EMA.Long.Period) return(0);
        
   int  counted_bars=IndicatorCounted();        
   if(counted_bars>0) 
   {
       int limit=Bars-counted_bars;
   }
   else
   {
       limit = Bars-EMA.Long.Period+1;
   }   
   
   while (limit >= 0)
   {                                      
      EMAFastBuffer[limit]=iMA(NULL,0,EMA.Short.Period,EMA.Short.Shift,EMA.Method,EMA.Applied.Price,limit);     
      EMASlowBuffer[limit]=iMA(NULL,0,EMA.Long.Period,EMA.Long.Shift,EMA.Method,EMA.Applied.Price,limit);  
      limit --;
   }    
   
   if(counted_bars>0)
   {
       limit= 0;
   }
   else
   {
       limit = iBarShift(NULL, 0 , firstTime);
   }
   
   while(limit >= 0)
   {  
       if (limit == 0) 
       {      
          if(!isNewBar()) break;
       }  

            upArrow[limit+1] = 0;
            downArrow[limit+1] = 0; 
      
            AvgRange = 0;              
            for (int counter=limit+1 ;counter<=limit+10;counter++)
            {
                AvgRange=AvgRange+MathAbs(High[counter]-Low[counter]);
            }
            double Range=AvgRange/10;
      
            if (!EMAShort.Above.EMALong && EMAFastBuffer[limit+1] < EMASlowBuffer[limit+1] && EMAFastBuffer[limit + 2] >= EMASlowBuffer[limit + 2])
            {                                                                              
                 downArrow[limit+1] = EMASlowBuffer[limit+1] + Range*0.3;
                 string alertStr = "Pair:" + Symbol() + ", T/F:" +  getTimeFrame(Period()) + ", Direction: SHORT, Price:" + DoubleToStr(Bid, Digits);                   
                 if (Text.Alert && limit == 0)
                 {
                     Alert(alertStr);
                     Print(alertStr);
                 }
                 if (Email.Alert && limit == 0)
                 {
                     SendMail("EMACross SHORT Alert" , alertStr);  
                 }
                 if (Sound.Alert && limit == 0)
                 {
                     PlaySound(SoundFileName);
                     lastAlertTime = TimeCurrent(); 
                     iterationTimes = 1;  
                 }                                                                                     
           }

           if (EMAShort.Above.EMALong && EMAFastBuffer[limit+1] > EMASlowBuffer[limit+1] && EMAFastBuffer[limit + 2] <= EMASlowBuffer[limit + 2])
           {               
                upArrow[limit+1] = EMASlowBuffer[limit+1] - Range*0.3;  
                alertStr = "Pair:" + Symbol() + ", T/F:" +  getTimeFrame(Period()) + ", Direction: LONG, Price:" + DoubleToStr(Ask, Digits);
            
                if (Text.Alert && limit == 0)
                 {
                     Alert(alertStr);
                     Print(alertStr);
                 }
                 if (Email.Alert && limit == 0)
                 {
                     SendMail("EMACross LONG Alert" , alertStr);  
                 }
                 if (Sound.Alert && limit == 0)
                 {
                     PlaySound(SoundFileName);
                     lastAlertTime = TimeCurrent();  
                     iterationTimes = 1; 
                 }                                                                    
           } 
      
      limit--;
   }
      
   if (Sound.Alert && iterationTimes < Max.Iterations && TimeCurrent() >= lastAlertTime + Interval.Secs)
   {   
       PlaySound(SoundFileName);
       
       lastAlertTime = TimeCurrent();
       iterationTimes ++;
   }
      
//---- done
   return(0);  
}

//==== Function: GlobalXXXXX ====================================
// FGM_BA -- Helper functions for access to Global Variables
bool GlobalCheck( string gname ) {
  if ( StringSubstr(gname, 0, 1) == "#" )
    return( GlobalVariableCheck(GlobalPrefixBase + gname) );
  else
    return( GlobalVariableCheck(GlobalPrefix + gname) );
}  
double GlobalGet( string gname ) {
  if ( StringSubstr(gname, 0, 1) == "#" )
    return( GlobalVariableGet(GlobalPrefixBase + gname) );
  else
    return( GlobalVariableGet(GlobalPrefix + gname) );
}  
bool GlobalSet( string gname, double gvalue ) {
  if ( StringSubstr(gname, 0, 1) == "#" )
    return( GlobalVariableSet(GlobalPrefixBase + gname, gvalue) );
  else
    return( GlobalVariableSet(GlobalPrefix + gname, gvalue) );
}  
bool GlobalDel( string gname ) {
  if ( StringSubstr(gname, 0, 1) == "#" )
    return( GlobalVariableDel(GlobalPrefixBase + gname) );
  else
    return( GlobalVariableDel(GlobalPrefix + gname) );
}  
  
bool isNewBar()
{    
    if (lastTime == Time[0]) 
    {        
        return (false);           
    }
    lastTime = Time[0];
    return (true); 
}

string getTimeFrame(int _Period)
{
    switch (_Period)
    {
        case 1: return ("M1");
                break;
        case 5: return ("M5");
                break;
        case 15: return ("M15");
                break;
        case 30: return ("M30");
                break;
        case 60: return ("H1");
                break;
        case 240: return ("H4");
                break;
        case 1440: return ("D1");
                break;
        case 10080: return ("W1");
                break;
        case 43200: return ("Month");
                break;
    }
}
 